package com.oceansoft.mobile.econsole.modules.base.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.oceansoft.mobile.econsole.common.constant.ConfigInfo;
import com.oceansoft.mobile.econsole.common.constant.Constant;
import com.oceansoft.mobile.econsole.common.editor.DateEditor;
import com.oceansoft.mobile.econsole.common.editor.DoubleEditor;
import com.oceansoft.mobile.econsole.common.editor.IntegerEditor;
import com.oceansoft.mobile.econsole.common.editor.LongEditor;
import com.oceansoft.mobile.econsole.common.util.HttpClientUtil;
import com.oceansoft.mobile.econsole.common.util.ServerInfo;
import com.oceansoft.mobile.econsole.modules.api.util.UserInfoUtil;
import com.oceansoft.mobile.econsole.modules.base.entity.ApiPager;
import com.oceansoft.mobile.econsole.modules.base.entity.Result;
import com.oceansoft.mobile.econsole.modules.member.entity.Member;
import com.oceansoft.mobile.econsole.modules.member.entity.WtMember;
import com.oceansoft.mobile.econsole.modules.member.service.IWtMemberService;
import com.oceansoft.mobile.econsole.modules.sys.entity.DictItem;
import com.oceansoft.mobile.econsole.modules.sys.entity.SysUser;
import com.oceansoft.mobile.econsole.modules.weixin.config.WxFactory;
import com.oceansoft.mobile.econsole.modules.weixin.entity.DeptBase;
import com.oceansoft.mobile.econsole.modules.weixin.entity.WxMember;
import com.oceansoft.mobile.econsole.modules.weixin.service.IWxMemberService;
import com.oceansoft.mobile.econsole.weixin.api.response.GetUserInfoResponse;
import com.oceansoft.mobile.econsole.weixin.api.response.OauthGetTokenResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.oceansoft.mobile.econsole.common.constant.Constant.*;

/**
 * 控制器基类<br/>提供基本类型数据转换、异常信息捕获、属性文件读取功能
 */
public abstract class BaseController {

    private static final Logger log = LoggerFactory.getLogger(BaseController.class);

    public static final String SIMPLE_DATE = new SimpleDateFormat("yyyyMMdd").format(new Date());

    @Resource
    protected ConfigInfo configInfo;

    @Resource
    private HttpServletRequest request;

    @Resource
    private ResourceBundleMessageSource messageSource;

    @Resource
    private IWxMemberService wxMemberService;

    @Resource
    private IWtMemberService wtMemberService;

    @InitBinder
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(int.class, new IntegerEditor());
        binder.registerCustomEditor(long.class, new LongEditor());
        binder.registerCustomEditor(double.class, new DoubleEditor());
        binder.registerCustomEditor(Date.class, new DateEditor());
    }

    /**
     * 记录操作日志
     *
     * @param message 日志内容
     */
    protected void log(String message) {
        request.setAttribute(Constant.OPERATION_LOG_CONTENT, message);
    }

    /**
     * 保存登录用户会话信息
     *
     * @param sysUser 待存储于session数据
     */
    public void saveSession(SysUser sysUser) {
        request.getSession().setAttribute(SESSION_USER, sysUser);
    }

    /**
     * 保存微信用户会话信息
     *
     * @param member 待存储于session数据
     */
    public void saveWxMemberSession(WtMember member) {
        request.getSession().setAttribute(SESSION_MEMBER, member);
    }

    /**
     * 获取当前登录用户Session信息
     *
     * @return SysUser
     */
    protected SysUser getSession() {
        Object sessionObj = request.getSession().getAttribute(SESSION_USER);
        if (null != sessionObj && sessionObj instanceof SysUser)
            return (SysUser) sessionObj;
        return null;
    }

    /**
     * 获取微信用户Session信息
     *
     * @return SysUser
     */
    protected WtMember getWxMemberSession() {
        Object sessionObj = request.getSession().getAttribute(Constant.SESSION_MEMBER);
        if (null != sessionObj && sessionObj instanceof WtMember)
            return (WtMember) sessionObj;
        return null;
    }

    /**
     * 保存用户权限信息
     *
     * @param resources 权限对应的资源集合
     */
    public void savePrivilege(Set<String> resources) {
        if (null != resources)
            request.getSession().setAttribute(SESSION_USER_PRIVILEGE, resources);
    }

    /**
     * 获取字典项
     *
     * @param dictKey 字典项KEY
     * @return 字典Value
     */
    protected DictItem getDictItem(String dictKey) {
        return (DictItem) request.getSession().getServletContext().getAttribute(dictKey);
    }

    protected Map<String, String> getDicts(String key) {
        return (Map<String, String>) request.getSession().getServletContext().getAttribute(key);
    }

    /**
     * 更新上下文里字典数据
     *
     * @param dictItem 字典对象
     */
    protected void updateDictItem(DictItem dictItem) {
        request.getSession().getServletContext().setAttribute(dictItem.getKey(), dictItem);
    }

    /**
     * 获取同类型字典项集合
     *
     * @param dictGroup 字典类型ID
     * @return List<DictItem>
     */
    protected List<DictItem> getDictItems(String dictGroup) {
        return new ArrayList<DictItem>();
    }

    /**
     * 将系统磁盘绝对地址转换为外部可访问的URL路径
     *
     * @param path 绝对路径
     * @return 外部可访问的URL路径
     */
    public String transFilePath2Url(String path) {
        return String.format("%s/%s/%s", request.getContextPath(), configInfo.getFileDownloadRootUrl(), path);
    }

    @ExceptionHandler(Exception.class)
    public ModelAndView exception(Exception e, HttpServletRequest request) {
        request.setAttribute("exception", e);
        if (ServerInfo.isAjax(request) || request.getParameter("ajax") != null) {
            return ajaxDoneError(e.getMessage());
        }
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("statusCode", 300);
        mav.addObject("message", e.getMessage());
        e.printStackTrace();
        return mav;
    }

    protected ModelAndView ajaxDone(int statusCode, String message, String forwardUrl) {
        ModelAndView mav = new ModelAndView("ajaxDone");
        mav.addObject("statusCode", statusCode);
        mav.addObject("message", message);
        mav.addObject("forwardUrl", forwardUrl);
        return mav;
    }

    protected String getRequestUrl() {
        return String.format("http://%s:%d%s", request.getServerName(), request.getServerPort(), request.getRequestURI());
    }

    protected String getRequestHost() {
        return request.getRemoteHost();
    }

    /**
     * 获取本机IP地址
     *
     * @return 本地IP地址
     */
    protected String getLocalHostIP() {
        return request.getLocalAddr();
    }

    protected ModelAndView ajaxDoneError(String message) {
        return ajaxDone(300, message, "");
    }

    protected String getMessage(String key, Object... args) {
        return messageSource.getMessage(key, args, RequestContextUtils.getLocaleResolver(request).resolveLocale(request));
    }

    /**
     * 返回JSONP结果
     *
     * @param result 数据对象
     * @return ModelAndView
     */
    protected ModelAndView JSONP(final Result result) {
        return new ModelAndView("jsonPView", "result", result);
    }


    protected WxMember getWxMember(HttpServletRequest request) throws Exception {
        if (request.getSession().getAttribute("openid") != null && request.getSession().getAttribute("openid") != "20") {
            String openid = request.getSession().getAttribute("openid") + "";
            return wxMemberService.findByOpenId(openid);
        } else {
            String code = request.getParameter("code");
            if (!StringUtils.isEmpty(code)) {
                OauthGetTokenResponse token = WxFactory.buildOauthAPI().getToken(code);
                String openid = token.getOpenid();

                //WtMember member = wtMemberService.getWtMemberByOpenid(openid);
                WxMember member = wxMemberService.findByOpenId(openid);
                if (null == member) {
                    GetUserInfoResponse user = WxFactory.buildUserAPI().getUserInfo(openid);
                    member = new WxMember();
                    BeanUtils.copyProperties(member, user);
                    member.setId(UUID.randomUUID().toString());
                    member.setOpenId(user.getOpenid());
                    member.setHeadimgUrl(user.getHeadimgurl());
//                    member.setWxOpenId(event.getToUserName());
                    member.setCreateTime(new Date());
                    wxMemberService.saveWxMember(member);
                    log.debug("【individual_center】【" + openid + "】微信用户保存完毕");
                }
                request.getSession().setAttribute("openid", openid);
                return member;
            }
        }
        return null;
    }

    /**
     * 获取Session
     *
     * @return
     */
    public HttpSession getHttpSession() {
        return request.getSession(true);
    }

    /**
     * 获取 openId。去认证接口拿，放入session
     *
     * @param request
     * @return
     * @throws Exception
     */
    protected String getOpenId(HttpServletRequest request) throws Exception {
        HttpSession session = request.getSession();
        String openId = (String) session.getAttribute("openid");
        if (Strings.isNullOrEmpty(openId)) {
            String code = request.getParameter("code");
            if (!Strings.isNullOrEmpty(code)) {
                OauthGetTokenResponse token = WxFactory.buildOauthAPI().getToken(code);
                openId = token.getOpenid();
                session.setAttribute("openid", openId);
            }
        }
        return openId;
    }

    /**
     * 获取session中的OpenId
     *
     * @return
     */
    protected String getSessionOpenId() {
        return (String) request.getSession().getAttribute("openid");
    }

    /**
     * 通过openId获取用户信息
     *
     * @param openId
     * @return
     */
    protected WtMember getMemberByOpenId(String openId) {

        String url = configInfo.getServiceInterfaceAddress() + "/member/wx/" + openId;
        String str = null;
        try {
            str = HttpClientUtil.doGet(url);
        } catch (IOException e) {
        }
        Preconditions.checkNotNull(str, "获取用户接口数据失败");
        WtMember member = null;
        JSONObject jsonObject = JSON.parseObject(str);
        String data = jsonObject.getString("data");
        if (!Strings.isNullOrEmpty(data)) {
            member = UserInfoUtil.getWtMember(data);
            this.saveWxMemberSession(member);
        }

        return member;
    }

    /**
     * 根据用户ID获取用户信息
     *
     * @param userGuid
     * @return
     */
    public WtMember getMemberByGUid(String userGuid) {
        String url = configInfo.getServiceInterfaceAddress() + "/member/" + userGuid;
        String str = null;
        try {
            str = HttpClientUtil.doGet(url);
        } catch (IOException e) {
        }
        Preconditions.checkNotNull(str, "获取用户接口数据失败");
        JSONObject jsonObject = JSON.parseObject(str);
        WtMember member = UserInfoUtil.getWtMember(jsonObject.getString("data"));
        this.saveWxMemberSession(member);
        return member;
    }

    /**
     * 更新的字段部分更新（接口会处理实名制问题）
     *
     * @param member
     * @return
     */
    public Result updateMember(Member member) {
        String guid = member.getGuid();
        String url = configInfo.getServiceInterfaceAddress() + "/member/" + guid;
        JSONObject object = new JSONObject();

        // 非实名认证用户才可以更新证件与真实姓名
        String idCard = member.getIdCard();
        String certificate = member.getCertificate();//存放实名认证信息
        if (!Objects.equals("1", certificate) && (!Strings.isNullOrEmpty(idCard)) && !idCard.contains("********")) {
            object.put("realName", member.getRealName());
            object.put("idNum", idCard);
        }
        object.put("email", member.getEmail());

        // 设置地址
        String address = member.getAddress();
        if (!Strings.isNullOrEmpty(address)) {
            List<String> addressList = Splitter.on("-").splitToList(address);
            object.put("province", addressList.get(0));
            object.put("city", addressList.get(1));
            object.put("area", addressList.get(2));
            if (addressList.size() == 4) {
                object.put("address", addressList.get(3));
            }
        }
//        System.out.println(object);
        String str = HttpClientUtil.doPut(url, object);
        Preconditions.checkNotNull(str, "更新用户信息接口调用失败");
        JSONObject jsonObject = JSON.parseObject(str);
        boolean flag = jsonObject.getBooleanValue("succ");
        Result result = new Result();
        result.setSucc(flag);
        result.setMsg("修改个人信息失败： " + jsonObject.getString("msg"));
        if (flag) {
            // 更新缓存数据数据
            WtMember wxMember = getMemberByGUid(guid);
            result.setData(wxMember);//实名认证返回
            result.setMsg("修改个人信息成功");
        }
        return result;
    }

    /**
     * 忘记密码(重置密码)
     *
     * @param tel
     * @param passWd
     * @param btnSendCode
     * @return
     */
    public Result resetPassword(String tel, String passWd, String btnSendCode) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("acountId", tel);
        jsonObject.put("newpassword", passWd);
        jsonObject.put("smscode", btnSendCode);

        String url = configInfo.getServiceInterfaceAddress() + "/member/forget";
        String res = HttpClientUtil.doPut(url, jsonObject);

        JSONObject object = JSON.parseObject(res);
        boolean succ = object.getBooleanValue("succ");
        String code = object.getString("code");

        Result result = new Result(succ);
        result.setMsg("密码重置失败");
        if (succ && Objects.equals("212001", code)) {
            result.setMsg("密码重置成功");
        }

        return result;
    }

    /**
     * 获取所有区域接口
     *
     * @param guid= 0 为全国省份
     * @return "guid":"370634","regioncode":"370634","regionname":"长岛县","parentcode":"370600","sort":1,"lev":null
     */
    public Result getRegion(String guid) {
        String res = "";
        try {
            res = HttpClientUtil.doGet(configInfo.getServiceInterfaceAddress() + "/base/region/" + guid);
//            res = HttpClientUtil.doGet("http://172.17.100.132:9001/base/region/"+guid);
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject object = JSON.parseObject(res);
        List<DeptBase> json = JSON.parseArray(object.getString("data"), DeptBase.class);
        System.out.println(json.toString());
        return new Result(Result.SUCC, json);
    }

    /**
     * 通过区域获得部门信息
     *
     * @param matid 事项ID qxid 区县ID dsid 地市ID
     * @return "pageIndex": 1,    "totalPage": 1,    "pageSize": 100,    "totalRow": 7,    "list": [    {    "DEPT_NAME": "长岛县北长山边防派出所",    "WORKTIME": "1",    "ADDRESS": "1","ORGPHONE": "1","GUID": "037063426000","MAT_ID": "4B6B5FC9D7A53E5DE0530100007F0D4B","PARENT_BID": "370634000000","ROW_ID": 1}]
     */
    public Result getDeptByRegin(String matid, String qxid, String dsid, String ps) {
        String res = "";
        if (null == matid) {
            matid = "";
        }
        try {
            res = HttpClientUtil.doGet(configInfo.getServiceInterfaceAddress() + "/reservation/page?pi=1&ps=" + ps + "&qxid=" + qxid + "&dsid=" + dsid + "&matid=" + matid);
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject object = JSON.parseObject(res);

        ApiPager pager = JSON.parseObject(object.getString("data"), ApiPager.class);
        System.out.println(pager);
        return new Result(Result.SUCC, pager);
    }

    /**
     * 微信解绑
     *
     * @param guid
     * @param openId
     * @return
     */
    protected Result loginout(String guid, String openId) {
        String url = configInfo.getServiceInterfaceAddress() + "/member/wxlogin/" + guid + "/" + openId;
        String res = HttpClientUtil.doPostString(url, null);

        System.out.println(res);
        JSONObject object = JSON.parseObject(res);
        boolean succ = object.getBooleanValue("succ");
        String code = object.getString("code");
        String msg = object.getString("msg");

        Result result = new Result(succ);
        result.setMsg("解绑账号失败:" + msg);
        if (succ) {
            result.setMsg("解绑账号成功");
        }

        return result;
    }
}
